﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Multiprocessing.Core.Units
{
    public class TaskProcessingBlock : IProcessingBlock
    {
        #region Fields

        private readonly Action[] _actions;
        private readonly Task[] _tasks;

        #endregion

        #region Properties

        public int Size
        {
            get { return _actions.Length; }
        }

        public Action this[int index]
        {
            get { return _actions[index]; }
            set
            {
                if (!ReferenceEquals(_tasks[index], null) && _tasks[index].Status == TaskStatus.Running)
                {
                    throw new ProcessingUnitBlockedException();
                }
                _actions[index] = value;
            }
        }

        #endregion

        #region Constructors

        public TaskProcessingBlock(int size)
        {
            _actions = new Action[size];
            _tasks = new Task[size];
        }

        #endregion

        #region Methods

        public void StartAll()
        {
            for (int i = 0; i < _actions.Length; ++i)
            {
                if (!ReferenceEquals(_actions[i], null))
                {
                    _tasks[i] = Task.Factory.StartNew(_actions[i]);
                }
            }
        }

        public void StartOne(int index)
        {
            if (ReferenceEquals(_actions[index], null))
            {
                throw new ArgumentException();
            }
            _tasks[index] = Task.Factory.StartNew(_actions[index]);
        }

        public void WaitAll()
        {
            Task.WaitAll(_tasks);
        }

        public void WaitOne(int index)
        {
            _tasks[index].Wait();
        }

        public void Dispose()
        {
            foreach (Task task in _tasks)
            {
                task.Dispose();
            }
        }

        #endregion
    }
}
